package com.runa.rccprotocol.netservice.dtu;

import com.runa.protocol.dto.ModbusPoint;
import com.runa.protocol.dto.ModbusResponseData;
import com.runa.protocol.enums.ModbusDataType;
import com.runa.protocol.util.ByteUtil;
import com.runa.rccprotocol.netservice.modbus.ModbusRequest;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 2024/9/2 19:39
 * zhangYB
 */
@Data
@Slf4j
public class ModbusRtuResponse extends DtuResponse {


    private ModbusResponseData modbusResponse;

    private ModbusRequest modbusRequest;


    public ModbusRtuResponse() {
        super();
    }

    public ModbusRtuResponse(String address) {
        super(address);
    }



    @Override
    public short getTransSign() {
        return 0;
    }

    @Override
    public Object getData() {
        return null;
    }

    public Map<String, Object> analysis() {
        List<ModbusPoint> modbusPoints = modbusRequest.getModbusPoints();
        byte[] data = modbusResponse.getData();
        modbusPointValue(modbusPoints, data);
        return modbusPoints.stream().collect(Collectors.toMap(ModbusPoint::getCode, ModbusPoint::getValue, (e1, e2) -> e1));
    }

    private void modbusPointValue(List<ModbusPoint> points, byte[] bytes) {
        ModbusPoint startPoint = points.get(0);
        for (ModbusPoint point : points) {
            int regIdx = point.getAddress() - startPoint.getAddress();
            if (ModbusDataType.Modbus_Bit.equals(point.getDataType())) {
                point.setValue(ByteUtil.byteToBit(bytes[regIdx / 8], regIdx % 8));
            } else {
                if (ModbusDataType.Modbus_Boolean.equals(point.getDataType())) {
                    try {
                        point.setValue(ByteUtil.byteToBoolean(bytes, regIdx << 1, point.getDeviation(), point.getByteOrder()));
                    } catch (Exception e) {
                        log.error("", e);
                    }
                } else {
                    Object value = null;
                    switch (point.getDataType()) {
                        case Modbus_Int16:
                            value = ByteUtil.byteToShort(bytes, regIdx << 1, point.getByteOrder());
                            break;
                        case Modbus_UInt16:
                            value = ByteUtil.byteToUShort(bytes, regIdx << 1, point.getByteOrder());
                            break;
                        case Modbus_Int32:
                            value = ByteUtil.byteToInt(bytes, regIdx << 1, point.getByteOrder());
                            break;
                        case Modbus_UInt32:
                            value = ByteUtil.byteToUInt(bytes, regIdx << 1, point.getByteOrder());
                            break;
                        case Modbus_Float:
                            value = ByteUtil.byteToFloat(bytes, regIdx << 1, point.getByteOrder());
                            break;
                        case Modbus_Double:
                            value = ByteUtil.byteToDouble(bytes, regIdx << 1, point.getByteOrder());
                            break;
                        case Modbus_UTF8:
                            value = ByteUtil.byteToString(bytes, regIdx << 1, point.getByteOrder());
                        default:
                    }
                    point.setValue(value);
                }
            }
        }
    }



}
